/*!
 **************************************************************
 *                                                            *  
 *   .=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-.       *  
 *    |                     ______                     |      *  
 *    |                  .-"      "-.                  |      *  
 *    |                 /            \                 |      *  
 *    |     _          |              |          _     |      *  
 *    |    ( \         |,  .-.  .-.  ,|         / )    |      *  
 *    |     > "=._     | )(__/  \__)( |     _.=" <     |      *  
 *    |    (_/"=._"=._ |/     /\     \| _.="_.="\_)    |      *  
 *    |           "=._"(_     ^^     _)"_.="           |      *  
 *    |               "=\__|IIIIII|__/="               |      *  
 *    |              _.="| \IIIIII/ |"=._              |      *  
 *    |    _     _.="_.="\          /"=._"=._     _    |      *  
 *    |   ( \_.="_.="     `--------`     "=._"=._/ )   |      *  
 *    |    > _.="                            "=._ <    |      *  
 *    |   (_/                                    \_)   |      *  
 *    |                                                |      *  
 *    '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-='      *  
 *                                                            *  
 *           LASCIATE OGNI SPERANZA, VOI CH'ENTRATE           *  
 **************************************************************   
 ******************************************************************
 *  项目名称 : proxy
 *  文件描述 :
 *  文件名称 : listener.js
 *  版  本  : v1.0.0.0
 *  说  明  :  
 *  作  者  : night
 *  邮  箱  : 88962800@qq.com
 *  创建时间 : 2019:01-04 13:31 
 ******************************************************************
 Copyright © 2017-2019, All rights reserved.
 ******************************************************************
 */
import net from "net";
import event from "events";
import uuid from "uuid/v4";
import Context from "./requestContext";
let _ports = {};
let listeners = {
    add: function (listener) {
        if (!this[listener.token]) {
            this[listener.token] = [];
        }
        this[listener.token].push({port: listener.port, token: listener.token, listener: listener.listener});
    },
    remove: function (listener) {
        if (!this[listener.port] || !this[listener.port].length) {
            return;
        }
        if (!this[listener.port].length) {
            return;
        }
        let index = this[listener.port].find((e) => {
            return e.token == listener.token
        });
    },
    exist: function (port) {
        return this[port] && this[port].length;
    },
    getListener: function (port) {
        return this[port];
    }
};
/**
 * 监听器
 */
export default class Listener extends event {
    constructor(opts) {
        super();
        this.port = opts.port;
        this.proto = opts.proto || 'tcp';
        this.remote_port = opts.remote_port
        this.token = opts.token;
        this.listen();
    }

    listen() {
        let _this = this;
        //TODO 检查端口是否已被其它程序占用
        if (_ports[this.port]) {// 判断端口是已经在使用中
            throw new Error(`the server port has ben used  ${this.port}`);
        }
        _ports[this.port]=1;
        let server = listeners.getListener(this.port);
        if (server) {
            this.listener = server;
            return this;
        }
        server = net.createServer();
        server.on('error', (err) => {
            //_this.listen();
        });
        server.on("connection", (socket) => {
             let context = new Context(socket);
            _this.emit('connection',_this,context);
            socket.on('error', (code, reason) => {
                context.close();
            });
            socket.on('close',()=>{
                context.close();
            })
        });
        server.listen(_this.port, () => {
            _ports[_this.port] = 1;
            console.log("tunnel start port:", _this.port);
        });
        this.listener = server;
        listeners.add((this));
        return this;
    }
    close() {
        this.listener.close();
        delete _ports[this.port];
        listeners.remove(this);
        console.log('close tunnel ',this.port);
    }
}